[#503] 뷰(View)들을 UI 레이어로 분리한다#513
Conversation
There was a problem hiding this comment.
Code Review
본 풀 리퀘스트는 SwiftUI 뷰와 재사용 UI 컴포넌트를 DevLogPresentation에서 분리하여 새로운 DevLogUI 모듈을 도입하고, 이에 맞춰 아키텍처 규칙 및 프로젝트 설정을 업데이트합니다. 또한 RootViewDependencies, MainViewDependencies 등의 의존성 컨테이너와 TodoViewModelFactory를 도입하여 의존성 주입 방식을 개선합니다. 리뷰 피드백에서는 DevLogApp 내부의 WindowGroup에서 RootViewDependencies를 직접 생성하여 발생할 수 있는 불필요한 재생성 문제를 지적하며 @State 프로퍼티로 관리할 것을 권장하고 있으며, RootView 내에서 dependencies에 적용된 불필요한 @State 래핑을 제거하고 let 상수로 변경하도록 제안하고 있습니다.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| networkConnectivityUseCase: container.resolve(ObserveNetworkConnectivityUseCase.self), | ||
| systemThemeUseCase: container.resolve(ObserveSystemThemeUseCase.self), | ||
| trackAnalyticsEventUseCase: container.resolve(TrackAnalyticsEventUseCase.self), | ||
| dependencies: RootViewDependencies(container: container), |
There was a problem hiding this comment.
RootViewDependencies(container: container)를 WindowGroup 내부에서 직접 생성하여 RootView에 전달하고 있습니다. SwiftUI의 body는 여러 번 재평가(re-evaluate)될 수 있으므로, 이 과정에서 RootViewDependencies와 그 내부의 모든 Coordinator 및 ViewModel들이 매번 새로 생성되었다가 버려지는 비효율이 발생합니다.
이를 방지하기 위해 DevLogApp 구조체 내부에 @State private var rootDependencies: RootViewDependencies 프로퍼티를 선언하고, init 메서드에서 container를 사용해 한 번만 초기화한 뒤 이를 RootView에 전달하도록 수정하는 것을 권장합니다.
| dependencies: RootViewDependencies(container: container), | |
| dependencies: rootDependencies, |
| @Environment(\.diContainer) var container: DIContainer | ||
| @State var viewModel: RootViewModel | ||
| struct RootView: View { | ||
| @State private var dependencies: RootViewDependencies |
There was a problem hiding this comment.
dependencies는 내부에서 변경되지 않는 의존성 주입용 구조체이므로 @State로 선언할 필요가 없습니다. Swift의 새로운 Observation 프레임워크(@Observable)에서는 컨테이너 구조체가 단순 let 상수로 선언되어 있어도 내부의 @Observable 클래스 프로퍼티가 변경되면 SwiftUI 뷰가 올바르게 업데이트됩니다.
따라서 불필요한 @State 래핑을 제거하고 let 상수로 선언하는 것이 좋습니다.
| @State private var dependencies: RootViewDependencies | |
| let dependencies: RootViewDependencies |
| systemThemeUseCase: systemThemeUseCase, | ||
| trackAnalyticsEventUseCase: trackAnalyticsEventUseCase | ||
| )) | ||
| self._dependencies = State(initialValue: dependencies) |
🔗 연관된 이슈
🎯 의도
Presentation 레이어에 포함되어 있던 SwiftUI View를 별도 UI 레이어로 분리하여 View와 상태/비즈니스 흐름의 책임 경계를 명확히 하기 위함
📝 작업 내용
📌 요약
DevLogUI모듈 추가DevLogPresentation에서DevLogUI로 이동DevLogPresentation을 ViewModel, Store, Coordinator, Routing, 화면 상태 중심으로 정리DevLogApp에서 조립하도록 이동🔍 상세
DevLogUI타깃을 추가하고DevLogUI -> DevLogPresentation의존 방향으로 구성DevLogPresentation의 ViewModel을Sources/ViewModel단일 디렉토리에서 관리하도록 재배치WindowGroup에서 직접 진입하는RootView,TodoEditorWindowView를 App 레이어로 이동DevLogUI생성에 맞춰.github/workflows/build.yml의 Tuist clean 검증 경로 추가docs/DevLog.drawio,docs/graph.png, README 프로젝트 구조, DevLog architecture harness 문서 갱신📸 영상 / 이미지 (Optional)